package org.gwtEss.table.pages;

import java.util.ArrayList;

import org.gwtEss.client.GwtEss;
import org.gwtEss.other.Div;
import org.gwtEss.table.Tab;

import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;

public abstract class ScrollPageNavigation extends Composite implements NavigationWidget{
	ScrollScrollPanel scrollP = new ScrollScrollPanel();
	private ScrollNavWidget w;
	boolean firstTime = false;
//	private CellFormatter cellFormatter;
	NavWidget top = new NavWidget(), bottom = new NavWidget();
	
	final DockPanel dp = new DockPanel();
	
	int topHeight = 0; 
	public ScrollPageNavigation(final ScrollNavWidget w, final int pxHeight) {
		assert w instanceof ScrollNavWidget && w instanceof Widget:"ScrollPageNavigation should be of type Widget and ScrollNavWidget";
		this.w = w;
		scrollP.setHeight(pxHeight + "px");
//		FlexTable f = new FlexTable();
//		VerticalPanel v = new VerticalPanel();

		
		dp.add(top, DockPanel.NORTH);
		dp.add((Widget)w, DockPanel.CENTER);
		dp.add(bottom, DockPanel.SOUTH);

//		f.setCellPadding(0);
//		f.setCellSpacing(0);
//		f.setWidget(0, 0, top);
//		f.setWidget(1, 0, (Widget)w);
//		f.setWidget(2, 0, bottom);
		top.addStyleName("blue");
		bottom.addStyleName("yellow");
		scrollP.setWidget(dp);
		initWidget(scrollP);
		dp.setCellHeight(top, "0px");
//		this.cellFormatter = f.getCellFormatter();
//		cellFormatter.addStyleName(0, 0, "red");
//		cellFormatter.addStyleName(1, 0, "green");
//		cellFormatter.addStyleName(2, 0, "blue");
//		cellFormatter.setHeight(2, 0, "100%");
		scrollP.addScrollScrollListener(new ScrollScrollListener(){

			public void onScrollEnd() {
//				int px = (int)(scrollP.getScrollPosition()/oneScrollUnit);
				int height = scrollP.getScrollPosition();
//				GwtEss.log.debug("fHeight: " + fHeight + ", height: " + height + ", w.getHeight(): " + w.getHeight());

//				if (height + pxHeight)
				
//				if (height - topCellHeight > w.getHeight()){
//				if (height > topCellHeight && height < (topCellHeight + w.getHeight()) && (height + pxHeight) < (topCellHeight + w.getHeight()))
				
				
				if (height > topHeight && height < (topHeight+ w.getHeight()) && (height + pxHeight) < (topHeight + w.getHeight())){
//					GwtEss.log.debug("topHeight: " + topHeight + ", scroll position: " + height + ", view area: " + pxHeight + ", scrollableHeight: " + scrollableHeight);
					return;
				}
//				dp.setCellHeight(top, height + "px");
				setHeights(height);
				topHeight = height;
//				top.setHeight(height);
//					setCellHeight(height, 0);
				int h = scrollableHeight - height - w.getHeight();
//				dp.setCellHeight(bottom, h + "px");//TODO: do we really require this? 
//				bottom.setHeight(h);
//					setCellHeight(fHeight - height - w.getHeight(), 2);
				int startRow = height/Tab.ROW_HEIGHT; 
				onPageSelect(startRow, -1, -1);
//				GwtEss.log.debug("adjust: top: " + height + ", scroll position: " + height + ", view area: " + pxHeight + ", scrollableHeight: " + scrollableHeight + ", startRow: " + startRow);

			}
			
		});
/*		scrollP.addScrollHandler(new ScrollHandler(){

			public void onScroll(ScrollEvent event) {

			}
			
		});*/
	}
//	private int topCellHeight = 0;
/*	private void setTopCellHeight(int height){
		topCellHeight = height;
		if (height ==0 )
			cellFormatter.setVisible(0, 0, false);
		else{
			cellFormatter.setVisible(0, 0, true);
			cellFormatter.setHeight(0, 0, height + "px");
			
		}
	}*/
//	private void setCellHeight(int height, int rowNum){
//	private void setCellHeight(int height, Label lab){
		
		
		
		
//		if (lab == top)//TODO: optimize
//			topCellHeight = height;
//		if (height ==0 )
//			cellFormatter.setVisible(rowNum, 0, false);
//		else{
//			cellFormatter.setVisible(rowNum, 0, true);
//			cellFormatter.setHeight(rowNum, 0, height + "px");
//			
//		}
//	}
	PageNavigatorListenerCollection listeners = new PageNavigatorListenerCollection();
	public class PageNavigatorListenerCollection extends ArrayList<PageNavigatorListener>{
		public void firePageSelect(int startRow, int endRow, int pageNum){
			for (PageNavigatorListener listener: this)
				listener.onPageSelect(ScrollPageNavigation.this, startRow, endRow, pageNum);
		}
	}
	public void addPagesListener(PageNavigatorListener listener) {
		listeners.add(listener);
	}
	public void removePagesListener(PageNavigatorListener listener) {
		listeners.remove(listener);
	}

	
//	int scrollUnits, fHeight; 
	float oneScrollUnit = 1;
	private int scrollableHeight;
	public void render(int rowsPerPage, int dataListSize) {
//		setCellHeight(0, 0);
		scrollableHeight = dataListSize*Tab.ROW_HEIGHT;
//		top.setHeight(0);
//		bottom.setHeight(scrollableHeight - w.getHeight());
		
		dp.setHeight(w.getHeight() + "px");
		setHeights(0);
		
		//		cellFormatter.setVisible(0, 0, false);
		
//		f.setHeight(fHeight + "px");//TODO
		
//		scrollP.scrollToBottom();
//		scrollUnits = scrollP.getScrollPosition();
//		oneScrollUnit = (float)scrollUnits/(float)fHeight;
		scrollP.scrollToTop();
	}

	private void setHeights(int topHeight){
		
//		dp.setCellHeight((Widget)w, w.getHeight() + "px");
		int bottomHeight = scrollableHeight - w.getHeight() - topHeight;
		bottomHeight = bottomHeight < 0? 0: bottomHeight;
		dp.setCellHeight(bottom, bottomHeight + "px");
		dp.setCellHeight(top, topHeight + "px");
	}
	
	public void renderAndSelect(int rowsPerPage, int dataListSize, int pageNum) {
		// TODO Auto-generated method stub
		
	}

	public void setEnabled(boolean enabled) {
		// TODO Auto-generated method stub
		
	}

	public void setSelectedPage(int selectPageNum) {
		// TODO Auto-generated method stub
		
	}

	
	public class ScrollScrollPanel extends ScrollPanel{
		private ScrollScrollListenerCollection listeners; 
		public ScrollScrollPanel() {
			sinkEvents(Event.ONMOUSEMOVE | Event.ONSCROLL | Event.KEYEVENTS); 
		}
		private int lastEvent = -1;
		@Override
		public void onBrowserEvent(Event event) {
			if (
					(lastEvent == Event.ONSCROLL && event.getTypeInt() == Event.ONMOUSEMOVE) || 
					(lastEvent == Event.ONSCROLL && event.getTypeInt() == Event.ONKEYUP) )
				listeners.fireOnScrollEnd();
			lastEvent = event.getTypeInt();
			super.onBrowserEvent(event);
		}
		public void addScrollScrollListener(ScrollScrollListener listener){
			if (listeners == null) listeners = new ScrollScrollListenerCollection();
			listeners.add(listener);
		}
		public void removeScrollScrollListener(ScrollScrollListener listener){
			if (listeners != null)
				listeners.remove(listener);
		}
		
	}
	public class ScrollScrollListenerCollection extends ArrayList<ScrollScrollListener>{
		public void fireOnScrollEnd(){
			for (ScrollScrollListener listener: this){
				listener.onScrollEnd();
			}
		}
	}
	
	
	public interface ScrollScrollListener {
		public void onScrollEnd();
	}
	public abstract void onPageSelect(int startRow, int endRow,
			int pageNum);
	
	public interface ScrollNavWidget{
		public int getHeight();
	}

	private class NavWidget extends Label implements ScrollNavWidget{
		int height = -1;
		public void setHeight(int pxHeight) {
			this.height = pxHeight;
			super.setHeight(pxHeight + "px");
		}
		public int getHeight() {
			return height;
		}
	}
	
/*	private class NavWidget extends Div implements ScrollNavWidget{
		int height = -1;
		public NavWidget() {
			super("<!-- -->", true);
		}
		public void setHeight(int pxHeight) {
			this.height = pxHeight;
			super.setHeight(pxHeight + "px");
		}
		public int getHeight() {
			return height;
		}
		
	}*/
}
